package com.mgee.netty.server.netty;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.mgee.netty.server.protobuf.ImProto;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * 服务启动监听器
 *
 * @author mwan
 */
@Component
@Slf4j
public class NettyServerListener {
    /**
     * 创建bootstrap
     */
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    /**
     * BOSS
     */
    EventLoopGroup boss = new NioEventLoopGroup();
    /**
     * Worker
     */
    EventLoopGroup work = new NioEventLoopGroup();
    /**
     * 通道适配器
     */
    @Resource
    private ServerChannelHandlerAdapter channelHandlerAdapter;
    /**
     * 从配置中心获取NETTY服务器配置
     */
    @Value("${server.netty.port:10001}")
    private int NETTY_PORT;
    
    @Value("${server.netty.maxthreads:5000}")
    private int MAX_THREADS;

    /**
     * 关闭服务器方法
     */
    @PreDestroy
    public void close() {
        log.info("关闭服务器....");
        //优雅退出
        boss.shutdownGracefully();
        work.shutdownGracefully();
    }

    /**
     * 开启及服务线程
     */
    public void start() {
        serverBootstrap.group(boss, work)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, MAX_THREADS) //最大客户端连接数为1024  
                .handler(new LoggingHandler(LogLevel.INFO)).childOption(ChannelOption.SO_KEEPALIVE, true); ;
        try {
            //设置事件处理
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                	
                	ch.pipeline().addLast(new IdleStateHandler(30,0,0));
                	//ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                	ch.pipeline().addLast(new CustomProtobufInt32FrameDecoder());
                	ch.pipeline().addLast(new ProtobufDecoder(ImProto.ImMsg.getDefaultInstance()));
                	
                	
                	//ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                	ch.pipeline().addLast(new CustomProtobufInt32LengthFieldPrepender());
                	ch.pipeline().addLast(new ProtobufEncoder());
                	ch.pipeline().addLast(channelHandlerAdapter);
                }
            });
            log.info("netty服务器在[{}]端口启动监听", NETTY_PORT);
            ChannelFuture f = serverBootstrap.bind(NETTY_PORT).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("[出现异常] 释放资源", e);
            boss.shutdownGracefully();
            work.shutdownGracefully();
            log.info("服务已关闭！");
        }
    }
}